var crypto = require('crypto')
const config = require('config')
const axios = require('axios')
const xml2js = require('xml2js')
const xmlParser = new xml2js.Parser()


function md5(text) {
    return crypto.createHash('md5').update(text).digest('hex');
};
// 预定义的一些工具函数
function getNonceStr() {
    var text = ""
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
    for (var i = 0; i < 16; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length))
    }
    return text
}
function getPaySign(appId, timeStamp, nonceStr, package) {
    var stringA = 'appId=' + appId +
        '&nonceStr=' + nonceStr +
        '&package=' + package +
        '&signType=MD5' +
        '&timeStamp=' + timeStamp
    const { partnerKey } = config.get('Customer.wx')
    var stringSignTemp = stringA + '&key=' + partnerKey
    var sign = md5(stringSignTemp).toUpperCase()
    return sign
}
function getTradeId(attach) {
    var date = new Date().getTime().toString()
    var text = ""
    var possible = "0123456789"
    for (var i = 0; i < 5; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length))
    }
    var tradeId = 'ty_' + attach + '_' + date + text
    return tradeId
}

function getPrePaySign(args) {
    const { appId, mchId, body, nonce_str, notify_url, openId, orderId, sub_appid, sub_mch_id, ip, price, key } = args
    console.log('openId:', openId)
    var stringA = 'appid=' + appId +
        '&body=' + body +
        '&mch_id=' + mchId +
        '&nonce_str=' + nonce_str +
        '&notify_url=' + notify_url +
        '&openid=' + openId +
        '&out_trade_no=' + orderId +
        '&spbill_create_ip=' + ip +
        '&sub_appid=' + sub_appid +
        '&sub_mch_id=' + sub_mch_id +
        '&total_fee=' + price +
        '&trade_type=JSAPI'
    var stringSignTemp = stringA + '&key=' + key
    var sign = md5(stringSignTemp).toUpperCase()
    return sign
}

function wxSendData(appId, productIntro, mchId, sub_appid, sub_mch_id, nonceStr, notifyUrl, openId, tradeId, ip, price, sign) {
    const sendData = '<xml>' +
        '<appid>' + appId + '</appid>' +
        '<mch_id>' + mchId + '</mch_id>' +
        '<sub_appid>' + sub_appid + '</sub_appid>' +
        '<sub_mch_id>' + sub_mch_id + '</sub_mch_id>' +
        '<body>' + productIntro + '</body>' +
        '<nonce_str>' + nonceStr + '</nonce_str>' +
        '<notify_url>' + notifyUrl + '</notify_url>' +
        '<openid>' + openId + '</openid>' +
        '<out_trade_no>' + tradeId + '</out_trade_no>' +
        '<spbill_create_ip>' + ip + '</spbill_create_ip>' +
        '<total_fee>' + price + '</total_fee>' +
        '<trade_type>JSAPI</trade_type>' +
        '<sign>' + sign + '</sign>' +
        '</xml>'
    return sendData
}

function getWxCheckSign(args) {
    const { appId, mchId, tradeId, key,nonce_str,sub_appid,sub_mch_id } = args
    var stringA = 'appid=' + appId +
        '&mch_id=' + mchId + 
        '&nonce_str=' + nonce_str +
        '&out_trade_no=' + tradeId +
        '&sub_appid=' + sub_appid +
        '&sub_mch_id=' + sub_mch_id;
    var stringSignTemp = stringA + '&key=' + key;
    console.log("stringSignTemp:",stringSignTemp);
    var sign = md5(stringSignTemp).toUpperCase()
    return sign
}


function wxCheckOrderData(appId,mchId,sub_appid, sub_mch_id,tradeId,nonce_str,sign){
    const sendData = '<xml>' +
        '<appid>' + appId + '</appid>' +
        '<mch_id>' + mchId + '</mch_id>' +
        '<sub_appid>' + sub_appid + '</sub_appid>' +
        '<sub_mch_id>' + sub_mch_id + '</sub_mch_id>' +
        '<nonce_str>' + nonce_str + '</nonce_str>' +
        '<out_trade_no>' + tradeId + '</out_trade_no>' +
        '<sign>' + sign + '</sign>' +
        '</xml>'
    return sendData;
}

function getPayParams(prepayId, tradeId) {
    const nonceStr = getNonceStr()
    const timeStamp = new Date().getTime().toString()
    const package = 'prepay_id=' + prepayId
    const { sub_appid } = config.get('Customer.wx')
    const paySign = getPaySign(sub_appid, timeStamp, nonceStr, package)
    // 前端需要的所有数据, 都从这里返回过去
    const payParamsObj = {
        nonceStr: nonceStr,
        timeStamp: timeStamp,
        package: package,
        paySign: paySign,
        signType: 'MD5',
        tradeId: tradeId,
    }
    return payParamsObj
}
function getErrText(args) {
    const errText = {
        INVALID_REQUEST: {
            text: "参数错误"
        },
        NOAUTH: {
            text: "商户无此接口权限"
        },
        NOTENOUGH: {
            text: "余额不足"
        },
        ORDERPAID: {
            text: "商户订单已支付"
        },
        ORDERCLOSED: {
            text: "订单已关闭"
        },
        SYSTEMERROR: {
            text: "系统错误"
        },
        APPID_NOT_EXIST: {
            text: "APPID不存在"
        },
        MCHID_NOT_EXIST: {
            text: "MCHID不存在"
        },
        APPID_MCHID_NOT_MATCH: {
            text: "appid和mch_id不匹配"
        },
        LACK_PARAMS: {
            text: "缺少参数"
        },
        OUT_TRADE_NO_USED: {
            text: "商户订单号重复	"
        },
        SIGNERROR: {
            text: "签名错误"
        },
        XML_FORMAT_ERROR: {
            text: "XML格式错误"
        },
        REQUIRE_POST_METHOD: {
            text: "请使用post方法"
        },
        POST_DATA_EMPTY: {
            text: "post数据为空"
        },
        NOT_UTF8: {
            text: "编码格式错误"
        }
    }
    return errText[args].text
}
function post(url, data) {
    return new Promise(async (resolve, reject) => {
        try {
            const result = await axios.post(url, data)
            resolve(result)
        } catch (error) {
            reject(error)
        }
    })
}
function xml2json(data) {
    return new Promise(async (resolve, reject) => {
        try {
            xmlParser.parseString(data, (err, result) => {
                if (err) {
                    reject(error)
                } else {
                    resolve(result)
                }
            })

        } catch (error) {
            reject(error)
        }
    })
}
module.exports = {
    md5,
    wxSendData,
    getNonceStr,
    getTradeId,
    getPrePaySign,
    getErrText,
    getPayParams,
    xml2json,
    getWxCheckSign,
    wxCheckOrderData
}